/**
 * 
 */
package com.vision.core.sv.security;

import java.util.HashSet;
import java.util.Set;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

import com.vision.core.cm.db.data.Company;
import com.vision.core.cm.db.data.User;
import com.vision.core.cm.db.data.User.UserStatus;
import com.vision.core.sv.db.CustomSessionFactoryBean;
import com.vision.core.sv.db.mgr.UserManager;


/**
 * Utility class for accessing the current {@link User} session.
 * 
 * @author Mark
 *
 */
public class SessionUtils {

	// TODO See if we can @Autowired this
	private static UserManager userManager;
	
	static UserManager getUserManager() {
		if (userManager == null) {
			userManager = new UserManager();
			userManager.setSessionFactory(CustomSessionFactoryBean.getFactory());
		}
		return userManager;
	}
	
	/**
	 * Returns the currently logged in {@link User}.
	 * 
	 * TODO Check vs. database if the currently logged in {@link User} still exists.
	 * 
	 * @return
	 */
	public static User getUser() {
		SecurityContext context = SecurityContextHolder.getContext();
		Authentication auth = context.getAuthentication();
		Session session = (Session) (auth == null ? null : auth.getPrincipal());
		if (session == null)
			throw new IllegalStateException("No session exists for user.");
		
		User user = session.getUser();
		// FIXME 0 This will be very expensive. Cache the users into memcache.
		// TODO Find a way to invalidate sessions whose Users have been deactivated or deleted.
//		user = getUserManager().getById(user.getUsername());
		
		if (user == null)
			throw new IllegalStateException("The logged-in user no longer exists.");
		
		if (user.getStatus() != UserStatus.ACTIVE)
			throw new IllegalStateException("The logged-in user has been deactivated.");
		
		return user;
	}
	
	/**
	 * Returns the set of {@link Company}s the currently logged-in {@link User} is assigned to.
	 * 
	 * @return
	 */
	public static Set<Company> getCompanies() {
		SecurityContext context = SecurityContextHolder.getContext();
		Authentication auth = context.getAuthentication();
		Session session = (Session) (auth == null ? null : auth.getPrincipal());
		if (session == null)
			throw new IllegalStateException("No session exists for user.");
		
		User user = session.getUser();
		return new HashSet<Company>(user.getCompanies());
	}
	
	/**
	 * Convenience method to determine if the currently logged-in {@link User} is assigned
	 * to a {@link Company} that has the specified <tt>code</tt>.
	 * 
	 * @param code
	 * @return
	 */
	public static boolean hasCompanyCode(String code) {
		Set<Company> companies = getCompanies();
		for (Company company : companies)
			if (company.getCode().equals(code))
				return true;
		return false;
	}
	
}